package mainview;
import java.awt.Color;
import java.awt.Font;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Vector;

import georeference.FileRead;
import georeference.MapRead;
import TUIO.TuioClient;
import TUIO.TuioCursor;
import TUIO.TuioListener;
import TUIO.TuioObject;
import TUIO.TuioPoint;
import TUIO.TuioTime;

import processing.core.*;
import triangleindex.DymaxionProjection;
import triangleindex.Icosahedron;
import triangleindex.Operations;
import triangleindex.Triangle;
import triangleindex.point2d;

public class simpleTriangle extends PApplet{

										// triangle
	// ---------------------------------mapthing-------------------------------------//
	// Specify variables that will be needed everywhere, anytime here
	double[] v_x = new double[13];
	double[] v_y = new double[13];
	double[] v_z = new double[13];
	
	// test your class
	Icosahedron ico = null;
	// test your interaction
	int pan = 0; // 0 - translate
	float zoom = 1.0f; // zoom in zoom out


	//for state
	boolean showAdj = true;
	boolean reshape = false;

	//chosen triangle
	int chosenTri = -1;
	int secondTri = -1;

	int[] adjTriangle = new int[3];
	int[] jointNode = new int[3];
	
	PImage[] worldTexture = new PImage[21];

	int max_height = 600;
	int max_width = 800;

	float ori_x;
	float ori_y;

	int pan_x = 0;
	int pan_y = 0;
	int tempx = 0;
	int tempy = 0;

	int scale = 200;
	
	//the font
	PFont font;
	
	boolean rotate = false;

	// int[][4] = int{{1,2,3,1},{1,3,4,1},{1,4,5,1},{1,5,6,1},{1,2,6,1},
	// {2,3,8,2],{8,3,9,8},{9,3,4,9},{10,9,4,10],{5,10,4,5},
	// {5,11,10,5},{5,6,11,5},{11,6,7,11},{7,6,2,7},{8,7,2,8},
	// {12,9,10,12},{12,11,10,12},{12,11,7,12},{12,8,7,12}};

	// testing the projection

	DymaxionProjection dymaxion = new DymaxionProjection();

	int r = 30; // the radius of the triangle

	ArrayList<point2d> jointNodes = new ArrayList<point2d>();
	ArrayList<Triangle> possibleTriangle = new ArrayList<Triangle>();
	ArrayList<Operations> possibleOperation = new ArrayList<Operations>();
	int possblei = -1;
	int blend = 0;
	Triangle beginT = new Triangle();
	Triangle endT = new Triangle();
	boolean animated = false;
	int timechange = 10;
	Point2D rotatePoint = new Point2D.Float();
	double rotateAngle = 0;
	Point2D moveDis = new Point2D.Float();
	
	int startx = 0;
	int starty = 0;
	
	float viberate_y = 0;
	
	TuioProcessing tuioClient = null;

	
	
	// these are some helper variables which are used
	// to create scalable graphical feedback

	float scale_factor = 1;
	

	public void setup() {
	//	size(1920, 1080, P3D);
//		size(800, 600, P3D);
		size(1000, 600, P3D);
	   
		noStroke();
		smooth();

		setupTuio();
		setupFrame();
		setupFont();
		setupTexture();
		setupTrangles();
		setupWorldMap();
	//	setup3DIco();
		

	}

	private void setupTuio(){
		
		this.tuioClient = new TuioProcessing(this);
	}
	
  
	
	private void setupTexture() {
		// TODO Auto-generated method stub
		this.worldTexture[0] = loadImage("..\\resources\\1.gif");
		this.worldTexture[1] = loadImage("..\\resources\\1.gif");
		this.worldTexture[2] = loadImage("..\\resources\\2.gif");
		this.worldTexture[3] = loadImage("..\\resources\\3.gif");
		this.worldTexture[4] = loadImage("..\\resources\\4.gif");
		this.worldTexture[5] = loadImage("..\\resources\\5.gif");

		this.worldTexture[6] = loadImage("..\\resources\\6.gif");
		this.worldTexture[7] = loadImage("..\\resources\\7.gif");
		this.worldTexture[8] = loadImage("..\\resources\\8.gif");
		this.worldTexture[9] = loadImage("..\\resources\\9.gif");
		this.worldTexture[10] = loadImage("..\\resources\\10.gif");

		this.worldTexture[11] = loadImage("..\\resources\\11.gif");
		this.worldTexture[12] = loadImage("..\\resources\\12.gif");
		this.worldTexture[13] = loadImage("..\\resources\\13.gif");
		this.worldTexture[14] = loadImage("..\\resources\\14.gif");
		this.worldTexture[15] = loadImage("..\\resources\\15.gif");

		this.worldTexture[16] = loadImage("..\\resources\\16.gif");
		this.worldTexture[17] = loadImage("..\\resources\\17.gif");
		this.worldTexture[18] = loadImage("..\\resources\\18.gif");
		this.worldTexture[19] = loadImage("..\\resources\\19.gif");
		this.worldTexture[20] = loadImage("..\\resources\\20.gif");

	}

	private void setupFont() {
		// TODO Auto-generated method stub
		// set font
		font = loadFont("..\\resources\\Ziggurat-32.vlw");
	}

	private void setupFrame() {
		// TODO Auto-generated method stub
		// set frame
		this.max_width = this.width * 4;
		this.max_height = this.height * 3 / 4;
	}

	//prepare the triangle data
	private void setupWorldMap() {
		// TODO Auto-generated method stub

		for (int j = 0; j < ico.ball.size(); j++) {
			int[] Nodeindex = this.ico.ball.get(j).getNodeIndex();

			point2d p0 = this.dymaxion.convert_i_t_p(Nodeindex[0], Nodeindex);
			point2d p1 = this.dymaxion.convert_i_t_p(Nodeindex[1], Nodeindex);
			point2d p2 = this.dymaxion.convert_i_t_p(Nodeindex[2], Nodeindex);

			int[] px1 = { (int) (p0.x * scale), (int) (p1.x * scale),
					(int) (p2.x * scale) };
			int[] py1 = { this.max_height - (int) (p0.y * scale),
					this.max_height - (int) (p1.y * scale),
					this.max_height - (int) (p2.y * scale) };

			this.ico.ball.get(j).center.setLocation(
					(px1[0] + px1[1] + px1[2]) / 3.0,
					(py1[0] + py1[1] + py1[2]) / 3.0);

			float radi = (float) Math.abs(((py1[1] - py1[0]) * 2.0 / 3.0));
			ico.ball.get(j).setRadius(radi);

			// fix the problem by hand manually
			ico.ball.get(3).setX(
					(float) (ico.ball.get(4).getX() + Math.sin(Math.PI / 3.0)
							* radi)); // Math.sin(Math.PI/3.0)*radi*2)
			ico.setRadius(radi);
		}

	}

	private void setupTrangles() {
		// TODO Auto-generated method stub
		ico = new Icosahedron();
		ico.setMax_x(this.width);

		this.ori_x = ico.getOri_x();
		this.ori_y = ico.getOri_y();

	}

	public void draw() {
		
		background(255);

		drawText();

		this.drawTriImage();
		
		this.draw3DTriangle();

//		this.drawtuio();
	}

	
	public void updateScale(int scale){
		
		for (int j = 0; j < ico.ball.size(); j++) {
			int[] Nodeindex = this.ico.ball.get(j).getNodeIndex();

			point2d p0 = this.dymaxion.convert_i_t_p(Nodeindex[0],
					Nodeindex);
			point2d p1 = this.dymaxion.convert_i_t_p(Nodeindex[1],
					Nodeindex);
			point2d p2 = this.dymaxion.convert_i_t_p(Nodeindex[2],
					Nodeindex);

			int[] px1 = { (int) (p0.x * scale), (int) (p1.x * scale),
					(int) (p2.x * scale) };
			int[] py1 = { this.max_height - (int) (p0.y * scale),
					this.max_height - (int) (p1.y * scale),
					this.max_height - (int) (p2.y * scale) };

			this.ico.ball.get(j).center.setLocation(
					(px1[0] + px1[1] + px1[2]) / 3.0,
					(py1[0] + py1[1] + py1[2]) / 3.0);

			float radi = (float) Math.abs(((py1[1] - py1[0]) * 2.0 / 3.0));
			ico.ball.get(j).setRadius(radi);

			// fix the problem by hand manually
			ico.ball.get(3).setX(
					(float) (ico.ball.get(4).getX() + Math
							.sin(Math.PI / 3.0) * radi)); // Math.sin(Math.PI/3.0)*radi*2)
			ico.setRadius(radi);
		}
	}
	
	
	
	private void drawText() {
		// TODO Auto-generated method stub

		fill(0);
		textAlign(RIGHT);
		textMode(SCREEN);
		textFont(font, 32);
//		text("3-reset", this.width - 10, 40);
//		text("2-reshapt", this.width - 10, 80);
//		text("7-animation", this.width - 10, 120);
//		text("8-latitude", this.width - 10, 160);
//		text("9-longtitude", this.width - 10, 200);
//		text("l/r/u/d-trans", this.width - 10, 240);
//		text("z/x-zoom", this.width - 10, 280);
//		text("3-reset", this.width - 10, 320);
//		text("3-reset", this.width - 10, 360);
//		text("3-reset", this.width - 10, 400);
		text("framerate : " + this.frameRate, this.width - 10, 50);
		text("viberate : " + this.viberate_y, this.width - 10, 100);
		text("timechange : " + this.timechange, this.width - 10, 150);
		text("blend : " + this.blend, this.width - 10, 200);
	}

	
	private void setup3DIco()
	{
		/* Cartesian coordinates for the 12 vertices of icosahedron */

	
		
		v_x[1] = 0.420152426708710003;
		v_y[1] = 0.078145249402782959;
		v_z[1] = 0.904082550615019298;

		v_x[2] = 0.995009439436241649;
		v_y[2] = -0.091347795276427931;
		v_z[2] = 0.040147175877166645;

		v_x[3] = 0.518836730327364437;
		v_y[3] = 0.835420380378235850;
		v_z[3] = 0.181331837557262454;

		v_x[4] = -0.414682225320335218;
		v_y[4] = 0.655962405434800777;
		v_z[4] = 0.630675807891475371;

		v_x[5] = -0.515455959944041808;
		v_y[5] = -0.381716898287133011;
		v_z[5] = 0.767200992517747538;

		v_x[6] = 0.355781402532944713;
		v_y[6] = -0.843580002466178147;
		v_z[6] = 0.402234226602925571;

		v_x[7] = 0.414682225320335218;
		v_y[7] = -0.655962405434800777;
		v_z[7] = -0.630675807891475371;

		v_x[8] = 0.515455959944041808;
		v_y[8] = 0.381716898287133011;
		v_z[8] = -0.767200992517747538;

		v_x[9] = -0.355781402532944713;
		v_y[9] = 0.843580002466178147;
		v_z[9] = -0.402234226602925571;

		v_x[10] = -0.995009439436241649;
		v_y[10] = 0.091347795276427931;
		v_z[10] = -0.040147175877166645;

		v_x[11] = -0.518836730327364437;
		v_y[11] = -0.835420380378235850;
		v_z[11] = -0.181331837557262454;

		v_x[12] = -0.420152426708710003;
		v_y[12] = -0.078145249402782959;
		v_z[12] = -0.904082550615019298;

	}
	
	
	private void draw3DTriangle()
	{
		
		
		translate(58, 48, 0); 
		rotateY((float) this.viberate_y);
		box(40);
		
		
		
	//	size(5);
		int[] vx = new int[13];
		int[] vy = new int[13];
		int[] vz = new int[13];
		
		for(int i = 1; i <13 ; i ++)
		{
			vx[i] = (int) (v_x[i]*1000);
			vy[i] = (int) (v_y[i]*1000);
			vz[i] = (int) (v_z[i]*1000);
		}
		
		
		fill(20);
		
		for(int i = 1; i <11; i++ ){
			
			beginShape(LINE);
			vertex(vx[i], vy[i], vz[i]);
			vertex(vx[i+1], vy[i+1], vz[i+1]);
			vertex(vx[i+2], vy[i+2], vz[i+2]);
			vertex(vx[i], vy[i], vz[i]);
			endShape();
		}
		
		beginShape(LINE);
		vertex(vx[11], vy[11], vz[11]);
		vertex(vx[12], vy[12], vz[12]);
		vertex(vx[1], vy[1], vz[1]);
		vertex(vx[11], vy[11], vz[11]);
		endShape();
		
		beginShape(LINE);
		vertex(vx[12], vy[12], vz[12]);
		vertex(vx[1], vy[1], vz[1]);
		vertex(vx[2], vy[2], vz[2]);
		vertex(vx[12], vy[12], vz[12]);
		endShape();
		
	}
	
	private void drawTriImage() {

	//	scale(zoom);
		stroke(255);

		// after we got 2d points, we add pan parameters, so it can syned with
		// maps always

		for (int i = 0; i < ico.ball.size(); i++) {

			fill(0, 255, 0);

			int index = ico.ball.get(i).getTriIndex();

			if (this.chosenTri == i) {
				
				if (animated) {
				//	this.drawSingleTriangle(this.beginT,this.endT);
					this.drawSingleTriangle(this.possibleOperation.get(possblei));
					
				} else {
					this.drawSingleTriangle(index, 1);
					this.drawSingleTriangle(index, 2);
				}
				// --------------------------since here ,we draw the possible
				// changed possible
				
				
				if (this.possibleOperation != null) {
					for (int t = 0; t < this.possibleOperation.size(); t++) {
						this.drawSingleTriangle(possibleOperation.get(t).te);
						float r = (float) this.possibleOperation.get(t).te.getRadius();
						
						if(this.possibleOperation.get(t).te.getNewOrientation() == 1){
							r += r/2;
						}
						
						
						if(viberate_y > 10){
							viberate_y = -10;
						}else {
							viberate_y += 0.2/this.possibleOperation.size();
						}
						this.drawHightlight((int)this.possibleOperation.get(t).te.getX(), (int)(this.possibleOperation.get(t).te.getY() - r + viberate_y));
					}
				}
				
			}else{
				
				this.drawSingleTriangle(index, 1);
			}

			if (this.showAdj == true) {
				if ((ico.ball.get(i).getTriIndex() == this.adjTriangle[0])
						|| (ico.ball.get(i).getTriIndex() == this.adjTriangle[1])
						|| (ico.ball.get(i).getTriIndex() == this.adjTriangle[2])) {

					this.drawSingleTriangle(index, 3);
					continue;

				}
			}

			fill(255, 0, 0);

			textFont(font);
			String s = ico.ball.get(i).getTriIndex() + "";
		//	text(s, (int) (ico.ball.get(i).getX()),
		//			(int) (ico.ball.get(i).getY()));

			this.ico.reLocation(tempx, tempy);
//			System.out.println("TEMPX = " + tempx + "TEMPY = " + tempy);
			tempx = 0;
			tempy = 0;

			// this.ico.AdjustIcosa();

		}

	}

	private void drawSingleTriangle(Operations operations) {
		// TODO Auto-generated method stub
		if (timechange == 10) {

			
			// they are physically far far away
			if (operations.jointNode == null) {
				this.moveDis = operations.moveDis;
				this.rotateAngle = 1000;
				this.rotatePoint = null;

			} else {
				this.moveDis = null;
				this.rotateAngle = operations.angle;
				this.rotatePoint = operations.jointNode;	
			}
		}
		
		// TODO Auto-generated method stub
		if(timechange > 1){
		    timechange -= 0.5;
		}else if(timechange == 1){
			animated = false;
			timechange = 10;
			return;
		}
		
		double r = this.possibleOperation.get(possblei).tb.getRadius();
		int index = this.possibleOperation.get(possblei).tb.getTriIndex();
	//	b.rotate(angle/timechange, c);
		
		int[] px = { 0, (int) (-r * Math.sin(Math.PI / 3.0)),
				(int) (r * Math.sin(Math.PI / 3.0)) };
		int[] py = { (int) (0 - r), (int) (0 + r / 2.0), (int) (0 + r / 2.0) };

		fill(225, 125, 0, blend);
		
		blend += 5 /this.possibleOperation.size();
		if (blend > 255) {
			blend = 0;
		}
		
	
	    pushMatrix();
	    
	    if((this.rotatePoint!=null)&&(this.rotateAngle< 100)){
			translate((int) rotatePoint.getX(), (int) rotatePoint.getY());
			rotate((float) rotateAngle / timechange);
			translate(-(int) rotatePoint.getX(), -(int) rotatePoint.getY());
	    }else{
	    	
	    }
	 
		pushMatrix();
		
		if(moveDis!=null){
			translate((int) (this.possibleOperation.get(possblei).tb.getX() + moveDis.getX()/timechange), (int)(this.possibleOperation.get(possblei).tb.getY() +moveDis.getY()/timechange));
		}else{
			translate((int)this.possibleOperation.get(possblei).tb.getX(), (int)this.possibleOperation.get(possblei).tb.getY());

		}
		pushMatrix();
		rotate((float)(this.possibleOperation.get(possblei).tb.getTextureType()));
		beginShape();
		texture(this.worldTexture[index]);
		vertex(px[0], py[0], worldTexture[index].width / 2, 0);
		vertex(px[1], py[1], 0, worldTexture[index].height);
		vertex(px[2], py[2], worldTexture[index].width,
				worldTexture[index].height);

		endShape();
		
		popMatrix();
		popMatrix();
		popMatrix();
		
		///////////////////////////////////////////////////////////////
		/**
		fill(255, 255, 125, 80);
		pushMatrix();
		translate((int) b.getX(), (int) b.getY());

		pushMatrix();

		rotate((float)(b.getTextureType()));
		
		pushMatrix();
		rotate((float)angle/timechange);

		beginShape();
		
		vertex(px[0], py[0]);
		vertex(px[1], py[1]);
		vertex(px[2], py[2]);
	

		endShape();
		popMatrix();
		popMatrix();
		popMatrix();
		*/
	}



	// 1- normal draw 2-highlight draw 3-adjecent draw 4-possible draw
	private void drawSingleTriangle(int index, int state) {

		Triangle t = ico.getTriangleByIndex(index);

		Point2D c = t.getLocation();
		double r = t.getRadius();

		int[] px = { 0, (int) (-r * Math.sin(Math.PI / 3.0)),
				(int) (r * Math.sin(Math.PI / 3.0)) };
		int[] py = { (int) (0 - r), (int) (0 + r / 2.0), (int) (0 + r / 2.0) };

		if (state == 1) {

		} else if (state == 2) {
			fill(255, 255, 125, 80);
		} else if (state == 3) {
			fill(0, 125, 255, 80);
		}

		pushMatrix();
		translate((int) c.getX(), (int) c.getY());

		pushMatrix();

		rotate((float) t.getTextureType());
	//	System.out.println(t.getTextureType());

		beginShape();
		if (state == 1) {
			texture(this.worldTexture[index]);
			vertex(px[0], py[0], worldTexture[index].width / 2, 0);
			vertex(px[1], py[1], 0, worldTexture[index].height);
			vertex(px[2], py[2], worldTexture[index].width,
					worldTexture[index].height);
		} else if (state == 2) {
			vertex(px[0], py[0]);
			vertex(px[1], py[1]);
			vertex(px[2], py[2]);
		} else if (state == 3) {
			vertex(px[0], py[0]);
			vertex(px[1], py[1]);
			vertex(px[2], py[2]);
		} else if (state == 4) {
			vertex(px[0], py[0]);
			vertex(px[1], py[1]);
			vertex(px[2], py[2]);
		}

		endShape();
		popMatrix();
		popMatrix();

	}

	// 1- normal draw 2-highlight draw 3-adjecent draw 4-possible draw
	private void drawSingleTriangle(Triangle t) {

		Point2D c = t.getLocation();
		double r = t.getRadius();

		int[] px = { 0, (int) (-r * Math.sin(Math.PI / 3.0)),
				(int) (r * Math.sin(Math.PI / 3.0)) };
		int[] py = { (int) (0 - r), (int) (0 + r / 2.0), (int) (0 + r / 2.0) };

		fill(0, 225, 0, blend);
		blend -= 5/this.possibleOperation.size();
		if (blend < 0) {
			blend = 255;
		}
		pushMatrix();
		translate((int) c.getX(), (int) c.getY());
		pushMatrix();

		rotate((float) t.getTextureType());

		beginShape();

		vertex(px[0], py[0]);
		vertex(px[1], py[1]);
		vertex(px[2], py[2]);

		endShape();
		popMatrix();
		popMatrix();

	}

	private void drawHightlight(int x, int y) {
		// TODO Auto-generated method stub

		fill(0, 255, 0);
		
		pushMatrix();
		translate(x, y);
		beginShape();

		vertex(10,-20);
		vertex(-10,-20);
		vertex(-10,0);
		vertex(-30,0);
		vertex(0,20);
		vertex(30,0);
		vertex(10,0);
	
		endShape(CLOSE);
        popMatrix();	
	}
	
	
	public void mouseMoved(){
	
	}
	
	public void mousePressed(){
		mousePressed(this.mouseX,this.mouseY);
	}

	public void mousePressed(float mouseX, float mouseY) {
		
		// TODO Auto-generated method stub
		// called when the pointer enters the applet's rectangular area
        
		if (!this.reshape) {
			for (int i = 0; i < ico.ball.size(); i++) {
				boolean isin = ico.ball.get(i).isInside(mouseX, mouseY);
				if (isin) {
					if(i != chosenTri){
						this.reshape = true;
					}
					this.chosenTri = i;
					break;
				}
			}
		}
		
		
		
		//test tuio
		
		
	
		if (this.showAdj) {
			if (chosenTri != -1) {
				
				getPossibleOperation();
				
				
				
			}

			// get the second triangle

			if (this.reshape) {
				for (int i = 0; i < ico.ball.size(); i++) {
					boolean isin = ico.ball.get(i).isInside(mouseX, mouseY);
					if (isin) {
						secondTri = i;
						if(secondTri!= chosenTri){
						chosenTri = secondTri;	
						getPossibleOperation();
						}
						break;
					}
				}
			}

		}

	}

	private void getPossibleOperation() {
		// TODO Auto-generated method stub
		this.possibleOperation.clear();
		adjTriangle = (ico.findAdjacentTri(ico.ball.get(chosenTri)
				.getTriIndex()));

		this.possibleOperation = null;
		possibleOperation = ico.getPossibleChanges(chosenTri, adjTriangle);
       
		if(possibleOperation.size() == 0){
        	this.reshape = false;
        }
	}

	public void mouseReleased() {

		// TODO Auto-generated method stub
		
	
		/**
		 * if ((this.reshape) && (this.secondTri != -1)) { this.reshape = false;
		 * if ((ico.ball.get(secondTri).getTriIndex() == adjTriangle[0]) ||
		 * (ico.ball.get(secondTri).getTriIndex() == adjTriangle[1]) ||
		 * (ico.ball.get(secondTri).getTriIndex() == adjTriangle[2])) {
		 * 
		 * 
		 * ico.reshapeIco(chosenTri, secondTri); } }
		 */

		if (this.reshape) {
			/**
			if (possibleTriangle != null) {
				for (int i = 0; i < this.possibleTriangle.size(); i++) {
					boolean isin = this.possibleTriangle.get(i).isInside(
							mouseX, mouseY);
					if (isin) {

						beginT.copy(ico.ball.get(chosenTri));
						endT.copy(this.possibleTriangle.get(i));

						ico.ball.get(chosenTri).copy(
								this.possibleTriangle.get(i));
						
						this.animated = true;
						break;
					}
				}
			}
			**/
			
			if (possibleOperation != null) {
				for (int i = 0; i < this.possibleOperation.size(); i++) {
					boolean isin = this.possibleOperation.get(i).te.isInside(
							mouseX, mouseY);
					if (isin) {

				//		beginT.copy(ico.ball.get(chosenTri));
				//		endT.copy(this.possibleTriangle.get(i));

						ico.ball.get(chosenTri).copy(
								this.possibleOperation.get(i).te);
						possblei = i;
						this.reshape = false;
						this.animated = true;
						break;
					}
				}
			}
			
			
		}

		this.repaint();
	}

	// interaction part
	@Override
	public void keyPressed() {
		// TODO Auto-generated method stub
	//	tuioClient.keyEvent(this.keyEvent);
		
		if (key == '3') {

			sceneReset();
		}

		if (key == 'z') {
			this.zoom += 0.2;
			scale *= 1.05;
			this.updateScale(scale);
			
		}
		if (key == 'x') {
			this.zoom -= 0.1;
			if (this.zoom < 0) {
				this.zoom = 0;
			}
			scale *= 0.95;
			this.updateScale(scale);
		}
		
		if(key == 'f'){
			
			int center_x = this.width/2;
			int center_y = this.height/2;
			
		}

//		this.repaint();

		switch (keyCode) {
		// left
		case LEFT: {
			this.pan_x -= 1;
			tempx = -1;
			break;
		}
			// right
		case RIGHT: {
			this.pan_x += 1;
			tempx = 1;
			break;
		}
			// up
		case UP: {
			this.pan_y -= 10;
			tempy = -10;
			break;
		}
			// down
		case DOWN: {
			this.pan_y += 10;
			tempy = 10;
			
			break;
		}
		}

		this.ico.setOri_x(ori_x + pan_x);
		this.ico.setOri_y(ori_y + pan_y);

//		this.ico.reLocation(tempx, tempy);
		
		if(this.chosenTri >= 0){
		this.getPossibleOperation();
		}
	}
	
	
	public void startMove(int stx, int sty){
		startx = stx;
		starty = sty;
	}
	
	public void touchmove(int tox, int toy){
		
		if((tox - startx > 0)){
			this.keyCode = RIGHT;
			keyPressed();
		}else{
			this.keyCode = LEFT;
			keyPressed();
		}
		
		if((toy - starty)> 0){
			this.keyCode = DOWN;
			keyPressed();
		}else{
			this.keyCode = UP;
			keyPressed();
		}
		
		
		
	}

	private void sceneReset() {
		// TODO Auto-generated method stub
		this.ico = null;
		
		this.setupTrangles();
		this.setupWorldMap();

		this.pan_x = 0;
		this.pan_y = 0;
		// this.showAdj = false;
		this.reshape = false;
	
	}

	@Override
	public void keyReleased() {
		// TODO Auto-generated method stub
	
		if (key == '2') {
			this.reshape = !this.reshape;
	//		System.out.println("change");
		}

	}
	

	
	public void updateTuioObject(TuioObject tobj) {
		if(!this.reshape){
			
		     if(tobj.getSymbolID() == 4){
		    	 for (int i = 0; i < ico.ball.size(); i++) {
						boolean isin = ico.ball.get(i).isInside(tobj.getX()*this.width, tobj.getY()*this.height);
						if (isin) {
							
							this.chosenTri = i;
							break;
						}
					}
		     }
		     
		     
		   
		}
	if (this.showAdj) {
		if (chosenTri != -1) {
			
			/**
			this.possibleTriangle.clear();
			adjTriangle = (ico.findAdjacentTri(ico.ball.get(chosenTri)
					.getTriIndex()));

			this.possibleTriangle = null;
			possibleTriangle = ico
					.getPossibleChange(chosenTri, adjTriangle);
             */
			
			this.possibleOperation.clear();
			adjTriangle = (ico.findAdjacentTri(ico.ball.get(chosenTri)
					.getTriIndex()));

			this.possibleOperation = null;
			possibleOperation = ico.getPossibleChanges(chosenTri, adjTriangle);
			
		}

		// get the second triangle

		if (this.reshape) {
			for (int i = 0; i < ico.ball.size(); i++) {
				boolean isin = ico.ball.get(i).isInside(mouseX, mouseY);
				if (isin) {
					secondTri = i;
					this.jointNode = ico.ball.get(chosenTri).getNodeIndex();
					break;
				}
			}
		}

	}

	
	}
	
	public void removeTuioObject(TuioObject tobj) {
	
		
	}
	
	public void addTuioCursor(TuioCursor tcur) {
	  
		if(this.tuioClient.getTuioCursors().size()== 1){
			this.mousePressed(tcur.getX()*this.width,tcur.getY()*this.height);
		}
	}
	
	//when a cursor is moving on the screen
	public void updateTuioCursor(TuioCursor tcur) {
	
		if(this.tuioClient.getTuioCursors().size()>2){
		      int steps = tcur.getPath().size();  
		      if(steps>2){
			  TuioPoint begin = tcur.getPath().get(steps-2);
		      TuioPoint end = tcur.getPath().lastElement();
		      
		   //   pan_x = (int) ((end.getX() - begin.getX())*this.width);
		   //   pan_y = (int) ((end.getY() - begin.getY())*this.height);
		      
		    //  this.ico.setOri_x(ori_x + pan_x);
			//  this.ico.setOri_y(ori_y + pan_y);
	//		  System.out.println("this pan_x = "+pan_x + " pan_y: " + pan_y);
	
			  tempx = (int) ((end.getX() - begin.getX())*this.width);
			  tempy = (int) ((end.getY() - begin.getY())*this.height);
			  }
 		}
		
		if(this.tuioClient.getTuioCursors().size() == 2){
			
			  Vector tuioCursorList = tuioClient.getTuioCursors();
		      TuioCursor tcur1 = (TuioCursor)tuioCursorList.elementAt(0);
		      TuioCursor tcur2 = (TuioCursor)tuioCursorList.elementAt(1);

		      int steps = tcur.getPath().size();  
		      
		      if(steps>2){
			  
		      TuioPoint begin1 = tcur1.getPath().get(steps-2);
		      TuioPoint begin2 = tcur2.getPath().get(steps-2);

		      TuioPoint end1 = tcur1.getPath().lastElement();
		      TuioPoint end2 = tcur2.getPath().lastElement();
		      
		      double dis1 = begin1.getDistance(begin2);
		      double dis2 = end1.getDistance(end2);
		      
		      if(dis1<dis2){
		    	  this.scale *= 1.01;
		    	  this.updateScale(scale);
		    	  
		      }else if(dis1>dis2){
		    	  this.scale *= 0.995;
		    	  this.updateScale(scale);
		      }
		      
		      System.out.println("scale == " + this.scale);
		      
		      }
			  
		}
			
	}
	
	public void removeTuioCursor(TuioCursor tcur) {
		System.out.println(tcur.getSessionID());
		System.out.println("the number of cursor in client: " + tuioClient.getTuioCursors().size());
	}
	
	public void refresh(TuioTime bundleTime) {
		 redraw();
	}

	static public void main(String args[]) {
		PApplet.main(new String[] { "--bgcolor=#F0F0F0", "Springs" });
	}

	//test tuio
		public void drawtuio()
		{
		  textFont(font,18*scale_factor);
		  float obj_size = 60 *scale_factor; 
		  float cur_size = 15*scale_factor; 
		   
		  Vector tuioObjectList = tuioClient.getTuioObjects();
		  
		  for (int i=0;i<tuioObjectList.size();i++) {
		     TuioObject tobj = (TuioObject)tuioObjectList.elementAt(i);
		     stroke(0);
		     fill(0);
		     pushMatrix();
		     translate(tobj.getScreenX(width),tobj.getScreenY(height));
		     rotate(tobj.getAngle());
		     rect(-obj_size/2,-obj_size/2,obj_size,obj_size);
		     popMatrix();
		     fill(255);
		     text(""+tobj.getSymbolID(), tobj.getScreenX(width), tobj.getScreenY(height));
		   }
		   
		   Vector tuioCursorList = tuioClient.getTuioCursors();
		   for (int i=0;i<tuioCursorList.size();i++) {
		      TuioCursor tcur = (TuioCursor)tuioCursorList.elementAt(i);
		      Vector pointList = tcur.getPath();
		      
		      if (pointList.size()>0) {
		        stroke(0,0,255);
		        TuioPoint start_point = (TuioPoint)pointList.firstElement();;
		        for (int j=0;j<pointList.size();j++) {
		           TuioPoint end_point = (TuioPoint)pointList.elementAt(j);
		           line(start_point.getScreenX(width),start_point.getScreenY(height),end_point.getScreenX(width),end_point.getScreenY(height));
		           start_point = end_point;
		        }
		        
		        stroke(192,192,192);
		        fill(192,192,192);
		        ellipse( tcur.getScreenX(width), tcur.getScreenY(height),cur_size,cur_size);
		        fill(0);
		        text(""+ tcur.getCursorID(),  tcur.getScreenX(width)-5,  tcur.getScreenY(height)+5);
		      }
		   }
		   
		}
		
	
}
